﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Caching;
using System.Web.UI;
using OpenFlashChartLib.Controls;

[assembly: WebResource(OpenFlashChartControl.SwfObjectScript, "text/javascript")]

namespace OpenFlashChartLib.Controls
{
    public class OpenFlashChartControl : Control
    {
        public const string SwfObjectScript = "OpenFlashChartLib.Resources.swfobject.js";

        private string _uniqControlID;

        private string UniqControlID
        {
            get
            {
                if (_uniqControlID != null)
                    return _uniqControlID;

                _uniqControlID = Guid.NewGuid().ToString();
                return _uniqControlID;
            }
        }

        public OpenFlashParameters FlashRegisterParams
        {
            get
            {
                object viewStObj = ViewState["RegParams"];

                if (viewStObj != null)
                    return (OpenFlashParameters) viewStObj;

                return (OpenFlashParameters) (ViewState["RegParams"] = new OpenFlashParameters());
            }
        }

        /// <summary>
        /// Gets or sets url where the swf file of open flash chart located
        /// </summary>
        public string FlashUrl
        {
            get
            {
                if (string.IsNullOrEmpty(FlashRegisterParams.FlashFileUrl))
                    FlashRegisterParams.FlashFileUrl = OpenFlashSettings.FlashFileUrl;

                return FlashRegisterParams.FlashFileUrl;
            }
            set { FlashRegisterParams.FlashFileUrl = value; }
        }

        /// <summary>
        /// Gets or set open flash chart width
        /// </summary>
        public int Width
        {
            get { return FlashRegisterParams.Width; }
            set { FlashRegisterParams.Width = value; }
        }

        /// <summary>
        /// Gets or sets open flash chart height
        /// </summary>
        public int Height
        {
            get { return FlashRegisterParams.Height; }
            set { FlashRegisterParams.Height = value; }
        }

        /// <summary>
        /// Gets or sets url to data http handler wich you have to register in web.config
        /// </summary>
        public string DataHandlerUrl
        {
            get
            {
                object viewStObje = ViewState["dhurl"];
                if (viewStObje == null)
                {
                    return OpenFlashSettings.DataHandlerUrl;
                }
                return (string) viewStObje;
            }
            set { ViewState["dhurl"] = value; }
        }

        public EmbedScriptType EmbedScriptType
        {
            get
            {
                object viewStObj = ViewState["embType"];
                if (viewStObj == null)
                {
                    return EmbedScriptType.SwfObject;
                }
                return (EmbedScriptType) viewStObj;
            }
            set { ViewState["embType"] = value; }
        }

        public bool RegisterScript
        {
            get
            {
                object viewStObj = ViewState["regScr"];
                if (viewStObj == null)
                {
                    return true;
                }
                return (bool) viewStObj;
            }
            set { ViewState["regScr"] = value; }
        }

        /// <summary>
        /// Set this property to your http handler or page url which renders Graph object for current chart
        /// Do not set anything if you use DrawChart event to create Graph object
        /// </summary>
        public string SpecificDataHandler
        {
            get
            {
                object viewStObj = ViewState["specHanler"];
                if (viewStObj == null)
                {
                    return null;
                }
                return (string) viewStObj;
            }
            set { ViewState["specHanler"] = value; }
        }

        /// <summary>
        /// Handle this event to create graph object inside the page
        /// </summary>
        public event DrawChartEventHandler DrawChart;
        /// <summary>
        /// Handle this event to register client script to use with AJAX Script Manager
        /// </summary>
        public event RegisterScriptEventHandler ScriptRegister;

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            int random = DateTime.Now.Millisecond;
            var script = new StringBuilder();
            if (RegisterScript)
            {
                Page.ClientScript.RegisterClientScriptResource(GetType(), SwfObjectScript);
            }
            script.Append(BuildSwfRegisterScript());
            RegisterStarupScript(script.ToString());
        }

        protected virtual void RegisterStarupScript(string scriptBody)
        {
            Page.ClientScript.RegisterStartupScript(GetType(), ClientID + "_embed", scriptBody, true);
            if (ScriptRegister != null)
            {
                ScriptRegister(this, new RegisterScriptEventArgs(scriptBody));
            }
        }

        private string BuildSwfRegisterScript()
        {
            var sb = new StringBuilder();
            string flashUrl = Page.ResolveUrl(FlashUrl);

            sb.AppendFormat("swfobject.embedSWF('{0}', '{1}', '{2}', '{3}','9.0.0', 'expressInstall.swf',", flashUrl,
                            ClientID, Width, Height);
            sb.Append("{");
            sb.AppendFormat("'data-file':'{0}'", BuildDataUrl());
            sb.Append("}");
            sb.Append(");");

            return sb.ToString();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            writer.Write("<div id=\"");
            writer.Write(ClientID);
            writer.Write("\"></div>");
        }

        protected void OnDrawChart(DrawChartEventArgs e)
        {
            if (DrawChart != null)
                DrawChart(this, e);
        }

        private string BuildDataUrl()
        {
            if (!string.IsNullOrEmpty(SpecificDataHandler))
            {
                return Page.ResolveUrl(SpecificDataHandler);
            }

            return string.Format("{0}?{1}={2}",
                                 Page.ResolveUrl(DataHandlerUrl), OpenFlashSettings.HandlerGetControlParam,
                                 UniqControlID);
        }

        /// <summary>
        /// If you call this method DrawChart event fires to rebuild chart data
        /// The chart will display anything untill you call this method
        /// </summary>
        public virtual void BuildChart()
        {
            var ee = new DrawChartEventArgs();
            OnDrawChart(ee);
            ee.Graph.OnBuildComplete();
            if (ee.Graph != null)
            {
                Page.Cache.Add(UniqControlID, ee.Graph, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 10, 0),
                               CacheItemPriority.NotRemovable, null);
            }
            else
            {
                Page.Cache.Remove(UniqControlID);
            }
        }
    }
}